
import numpy as np
import networkx as nx
import random as rd
class Coupled_Network:
    def __init__(self, G, T):
        self.max_dis = 1e3
        self.N = len(G)
        self.T = T
        self.G = G
        # cnt = 0
        # for i in range(len(self.G)):
        #     for j in range(len(self.G)):
        #         if(self.G[i][j] > 0 and self.G[i][j] < 1e3):
        #             cnt += 1
        # print(cnt)
        self.edge = []#边集

    def get_edge_set(self):
        for i in range(0, self.N):
            for j in range(0, self.N):
                if(self.G[i][j] > 0 and self.G[i][j] < self.max_dis):
                    self.edge.append([i, j])

    def get_shortest_path(self):#得到最短距离矩阵与最短距离个数矩阵
        #若不考虑网络耦合，n2设置为0
        #空间网络满足三角形法则，删除不满足规则的边，保证满足三角形法则
        #print(self.G)
        self.num_d = np.zeros((self.N, self.N))
        self.d = self.G
        
        for i in range(0, self.N):
            for j in range(0, self.N):
                if(self.G[i][j] < self.max_dis):
                    self.num_d[i][j] = 1
        # print(self.num_d)
        # print(self.G)
        for k in range(0, self.N):
            for i in range(0, self.N):
                for j in range(0, self.N):
                    if(self.d[i][k] + self.d[k][j] == self.d[i][j]):
                        self.num_d[i][j] += self.num_d[i][k] * self.num_d[k][j]
                    if(self.d[i][k] + self.d[k][j] < self.d[i][j]):
                        self.d[i][j] = self.d[i][k] + self.d[k][j]
                        self.num_d[i][j] = self.num_d[i][k] * self.num_d[k][j]
        #print(self.d)
        # self.get_edge_set()
        # E = len(self.edge)#总边数
        # print(E)
        #print(np.sum(self.num_d))
    def get_avg_shortest_path(self):#平均最短路径
        #T为交通流分布矩阵，d为最短路径矩阵
        self.avg_d = 0
        for i in range(self.N):
            for j in range(self.N):
                self.avg_d += self.T[i][j] * self.d[i][j]
        return self.avg_d

    def get_edge_betweenness_centrality(self, a, b):#ab边的边介数
        ebc = np.zeros((self.N, self.N))
        for i in range(0, self.N):
            for j in range(0, self.N):
                if(self.num_d[i][j] == 0 or self.G[i][j] >= self.max_dis or self.d[i][j] == 0):
                    continue
                if(self.d[i][j] == self.d[i][a] + self.d[a][b] + self.d[b][j]):
                    ebc[i][j] += self.num_d[i][a] * self.num_d[b][j] / self.num_d[i][j]
        for i in range(0, self.N):
            for j in range(0, self.N):
                if(self.num_d[i][j] == 0 or self.G[i][j] >= self.max_dis or self.d[i][j] == 0): 
                    continue
                ebc[i][j] = self.T[i][j] * ebc[i][j] / self.num_d[i][j]
        return np.sum(ebc)


    def get_gini(self):#交通流分布基尼系数
        self.get_edge_set()
        E = len(self.edge)#总边数
        ebc = []
        avg_x = 0
        for ep in self.edge:
            xp = self.get_edge_betweenness_centrality(ep[0], ep[1])
            avg_x += xp
            ebc.append(xp)
        #print(len(E))
        gini = 0
        for i in range(len(ebc)):
            for j in range(len(ebc)):
                if(i != j):
                    gini += abs(ebc[i] - ebc[j])
        gini = gini / (2 * E * avg_x)
        self.gini = gini
        return self.gini
    def get_utility(self, miu):
        self.utility = self.avg_d + miu * self.gini
        return self.utility

    